package com.yykj.hospital.server.service.banci.impl;

import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.yykj.common.enums.BanCiType;
import com.yykj.hospital.client.dto.DoctorDTO;
import com.yykj.hospital.server.dto.banci.SettingImportDTO;
import com.yykj.hospital.server.form.ProtoDoctorSearchForm;
import com.yykj.hospital.server.model.entity.banci.HospitalBanCi;
import com.yykj.hospital.server.model.entity.banci.HospitalDoctorVisitLevel;
import com.yykj.hospital.server.model.entity.banci.HospitalDoctorVisitSetting;
import com.yykj.hospital.server.model.repository.banci.HospitalBanCiRepository;
import com.yykj.hospital.server.model.repository.banci.HospitalDoctorVisitLevelRepository;
import com.yykj.hospital.server.model.repository.banci.HospitalDoctorVisitSettingRepository;
import com.yykj.hospital.server.service.HospitalDoctorService;
import com.yykj.hospital.server.service.banci.BanCiImportService;
import com.yykj.hospital.server.service.banci.BanCiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class BanCiImportServiceImpl implements BanCiImportService {
    @Override
    public boolean checkAppointmentVisitSetting(Integer hospitalId, ExcelImportResult<SettingImportDTO> result) {
        checkBanCiExist(hospitalId, BanCiType.appointment, result);
        checkDoctorMatch(hospitalId, result);
        checkAppointLevel(hospitalId, result);
        return result.getFailList().size() == 0;
    }

    @Override
    public void importAppointmentVisitSetting(Integer hospitalId, List<SettingImportDTO> list) {
        List<HospitalDoctorVisitSetting> settingList = new ArrayList<>();
        List<String> doctorIds = new ArrayList<>();
        for (SettingImportDTO importDTO : list) {
            doctorIds.add(importDTO.getDoctorId());
        }
        List<HospitalDoctorVisitSetting> oldSettingList = hospitalDoctorVisitSettingRepository
                .findAllByHospitalIdAndTypeAndDoctorIdIn(hospitalId, BanCiType.appointment, doctorIds);
        Map<String, HospitalDoctorVisitSetting> map = new HashMap<>();
        for (HospitalDoctorVisitSetting visitSetting : oldSettingList) {
            map.put(visitSetting.getDoctorId() + visitSetting.getBanCiId(), visitSetting);
        }

        for (SettingImportDTO importDTO : list) {
            HospitalDoctorVisitSetting setting = new HospitalDoctorVisitSetting();
            BeanUtils.copyProperties(importDTO, setting);
            setting.setHospitalId(hospitalId);
            setting.setLevelName(importDTO.getLevelName());
            setting.setType(BanCiType.appointment);
            HospitalDoctorVisitSetting visitSetting = map.get(importDTO.getDoctorId() + importDTO.getBanCiId());
            if (visitSetting != null) {
                setting.setId(visitSetting.getId());
            }

            settingList.add(setting);

        }
        hospitalDoctorVisitSettingRepository.saveAll(settingList);
    }

    @Override
    public boolean checkOnlineVisitSetting(Integer hospitalId, ExcelImportResult<SettingImportDTO> result) {

        checkBanCiExist(hospitalId, BanCiType.online, result);
        checkDoctorMatch(hospitalId, result);
        return result.getFailList().size() == 0;
    }

    @Override
    public void importOnlineVisitSetting(Integer hospitalId, List<SettingImportDTO> list) {
        List<HospitalDoctorVisitSetting> settingList = new ArrayList<>();
        List<String> doctorIds = new ArrayList<>();
        for (SettingImportDTO importDTO : list) {
            doctorIds.add(importDTO.getDoctorId());
        }
        List<HospitalDoctorVisitSetting> oldSettingList = hospitalDoctorVisitSettingRepository
                .findAllByHospitalIdAndTypeAndDoctorIdIn(hospitalId, BanCiType.online, doctorIds);
        Map<String, HospitalDoctorVisitSetting> map = new HashMap<>();
        for (HospitalDoctorVisitSetting visitSetting : oldSettingList) {
            map.put(visitSetting.getDoctorId() + visitSetting.getBanCiId(), visitSetting);
        }

        for (SettingImportDTO importDTO : list) {
            HospitalDoctorVisitSetting setting = new HospitalDoctorVisitSetting();
            BeanUtils.copyProperties(importDTO, setting);
            setting.setHospitalId(hospitalId);
            setting.setAppointment(0);
            setting.setType(BanCiType.online);
            HospitalDoctorVisitSetting visitSetting = map.get(importDTO.getDoctorId() + importDTO.getBanCiId());
            if (visitSetting != null) {
                setting.setId(visitSetting.getId());
            }

            settingList.add(setting);

        }
        hospitalDoctorVisitSettingRepository.saveAll(settingList);
    }

    /**
     * 检查 班次是否存在
     *
     * @param hospitalId
     * @param type
     * @param result
     * @return
     */
    private void checkBanCiExist(Integer hospitalId, BanCiType type, ExcelImportResult<SettingImportDTO> result) {
        List<HospitalBanCi> hospitalBanCiList = banCiRepository.findAllByHospitalIdAndStatusAndTypeOrderByStartTime(hospitalId, true, type);
        Iterator<SettingImportDTO> iterator = result.getList().iterator();
        while (iterator.hasNext()) {
            SettingImportDTO next = iterator.next();
            boolean flag = false;
            for (HospitalBanCi hospitalBanCi : hospitalBanCiList) {
                if (!hospitalBanCi.getStartTime().isAfter(next.getStartTime()) && !hospitalBanCi.getEndTime().isBefore(next.getEndTime())) {
                    flag = true;
                    next.setBanCiId(hospitalBanCi.getId());
                    next.setBanCiName(hospitalBanCi.getName());
                    break;
                }
            }
            if (!flag) {//时间段非法
                next.setErrorMsg(next.getBanCiTime() + "没有班次包含该时间段");
                result.getFailList().add(next);
                iterator.remove();
            }
        }

    }

    private void checkAppointLevel(Integer hospitalId, ExcelImportResult<SettingImportDTO> result) {
        Map<String, HospitalDoctorVisitLevel> map = getHospitalVisitLevelMap(hospitalId);
        Iterator<SettingImportDTO> iterator = result.getList().iterator();
        while (iterator.hasNext()) {
            SettingImportDTO next = iterator.next();
            HospitalDoctorVisitLevel level = map.get(next.getLevelName());
            if (level == null) {
                next.setErrorMsg(next.getLevelName() + " 预约级别不存在");
                result.getFailList().add(next);
                iterator.remove();
            } else {
                if (!level.getStatus()) {
                    next.setErrorMsg(next.getLevelName() + " 预约级别已禁用");
                    result.getFailList().add(next);
                    iterator.remove();
                }
                next.setLevelId(level.getId());
                next.setLevelName(level.getName());
            }
        }

    }

    private Map<String, HospitalDoctorVisitLevel> getHospitalVisitLevelMap(Integer hospitalId) {
        List<HospitalDoctorVisitLevel> visitLevelList = visitLevelRepository.findAllByHospitalId(hospitalId);
        Map<String, HospitalDoctorVisitLevel> map = new HashMap<>();
        for (HospitalDoctorVisitLevel level : visitLevelList) {
            map.put(level.getName(), level);
        }
        return map;
    }

    private void checkDoctorMatch(Integer hospitalId, ExcelImportResult<SettingImportDTO> result) {
        ProtoDoctorSearchForm form = new ProtoDoctorSearchForm();
        form.setHospitalId(hospitalId);
        for (SettingImportDTO dto : result.getList()) {
            form.getJobNumList().add(dto.getJobNum());
        }
        List<DoctorDTO> hospitalDoctor = doctorService.getHospitalDoctor(form);
        Map<String, DoctorDTO> mapDoctor = new HashMap<>();
        for (DoctorDTO dto : hospitalDoctor) {
            mapDoctor.put(dto.getJobNum(), dto);
        }

        Iterator<SettingImportDTO> iterator = result.getList().iterator();
        while (iterator.hasNext()) {
            SettingImportDTO next = iterator.next();
            DoctorDTO doctorDTO = mapDoctor.get(next.getJobNum());
            if (doctorDTO == null) {
                next.setErrorMsg(" 工号：[" + next.getJobNum() + "]医生不存在");
                result.getFailList().add(next);
                iterator.remove();
            } else {
                if (!doctorDTO.getDepName().equals(next.getDepName())) {
                    next.setErrorMsg("科室名称不匹配:" + doctorDTO.getDepName() + " " + next.getDepName());
                    result.getFailList().add(next);
                    iterator.remove();
                }
                next.setDoctorId(doctorDTO.getDoctorId());
                next.setDepId(doctorDTO.getDepId());
                next.setPy(doctorDTO.getPy());
                next.setWb(doctorDTO.getWb());
            }

        }
    }



    private HospitalBanCiRepository banCiRepository;

    private HospitalDoctorVisitSettingRepository hospitalDoctorVisitSettingRepository;

    private HospitalDoctorVisitLevelRepository visitLevelRepository;

    private HospitalDoctorService doctorService;


    @Autowired
    public void setBanCiRepository(HospitalBanCiRepository banCiRepository) {
        this.banCiRepository = banCiRepository;
    }

    @Autowired
    public void setHospitalDoctorVisitSettingRepository(HospitalDoctorVisitSettingRepository hospitalDoctorVisitSettingRepository) {
        this.hospitalDoctorVisitSettingRepository = hospitalDoctorVisitSettingRepository;
    }

    @Autowired
    public void setVisitLevelRepository(HospitalDoctorVisitLevelRepository visitLevelRepository) {
        this.visitLevelRepository = visitLevelRepository;
    }

    @Autowired
    public void setDoctorService(HospitalDoctorService doctorService) {
        this.doctorService = doctorService;
    }
}
